﻿#include"XQHttpHeadObject.h"
#include<QList>
XQHttpHeadObject::XQHttpHeadObject(const QByteArray& header)
{
	if(header.isEmpty())
		init();
	else
		setData(header);
}

Http::Versions XQHttpHeadObject::getVersions(const QString& text)
{
	using Type = Http::Versions;
	auto list = text.split("/");
	if (list.size() > 1)
	{
		auto type = list[1].trimmed();
		if (type == "1.0")
			return Type::HTTP1;
		else if (type == "1.1")
			return Type::HTTP11;
		else if (type == "2")
			return Type::HTTP2;
		else if (type == "3")
			return Type::HTTP3;
	}
	return Type::HTTP11;
}

QByteArray XQHttpHeadObject::toByteArray() const
{
	return header_toByteArray()+"\r\n"+ m_content;
}

QString XQHttpHeadObject::toStrinng() const
{
	return QString(toByteArray());
}

Http::Versions XQHttpHeadObject::versions() const
{
	return m_versions;
}

QByteArray XQHttpHeadObject::versions_toByteArray() const
{
	using Type = Http::Versions;
	QByteArray byte;
	if (m_versions == Type::HTTP1)
		byte += "1";
	else if (m_versions == Type::HTTP11)
		byte += "1.1";
	else if (m_versions == Type::HTTP2)
		byte += "2";
	else if (m_versions == Type::HTTP3)
		byte += "3";
	return "HTTP/" + byte;
}

QString XQHttpHeadObject::versions_toString() const
{
	return versions_toByteArray();
}

QByteArray XQHttpHeadObject::header_toByteArray() const
{
	QByteArray byte;
	for (auto it=m_header.begin();it!=m_header.end();it++)
	{
		auto& key = it.key();
		auto& value = it.value();
		byte += (key+": "+value+"\r\n");
	}
	return byte;
}

const QHash<QByteArray, QByteArray>& XQHttpHeadObject::header() const
{
	return m_header;
}

QHash<QByteArray, QByteArray>& XQHttpHeadObject::header()
{
	return m_header;
}

bool XQHttpHeadObject::headerIsEmpty() const
{
	return m_header.isEmpty();
}

QByteArray XQHttpHeadObject::header(const QByteArray& headerName) const
{
	return m_header[headerName];
}

QByteArray XQHttpHeadObject::header(QNetworkRequest::KnownHeaders header) const
{
	switch (header)
	{
	case QNetworkRequest::ContentTypeHeader:return this->header("Content-Type");
		break;
	case QNetworkRequest::ContentLengthHeader:return this->header("Content-Length");
		break;
	case QNetworkRequest::LocationHeader:return this->header("Location");
		break;
	case QNetworkRequest::LastModifiedHeader:return this->header("Last-Modified");
		break;
	case QNetworkRequest::CookieHeader:return this->header("Cookie");
		break;
	case QNetworkRequest::SetCookieHeader:return this->header("Set-Cookie");
		break;
	case QNetworkRequest::ContentDispositionHeader:return this->header("Content-Disposition");
		break;
	case QNetworkRequest::UserAgentHeader:return this->header("User-Agent");
		break;
	case QNetworkRequest::ServerHeader:return this->header("Server");
		break;
	case QNetworkRequest::IfModifiedSinceHeader:return this->header("If-Modified-Since");
		break;
	case QNetworkRequest::ETagHeader:return this->header("ETag");
		break;
	case QNetworkRequest::IfMatchHeader:return this->header("If-Match");
		break;
	case QNetworkRequest::IfNoneMatchHeader:return this->header("If-None-Match");
		break;
	default:
		break;
	}
	return QByteArray();
}

QString XQHttpHeadObject::host() const
{
	auto list = m_header["Host"].split(':');
	if(list.isEmpty())
		return QString();
	return list[0];
}

quint16 XQHttpHeadObject::port() const
{
	auto list = m_header["Host"].split(':');
	if (list.size()<2)
		return -1;
	return list[1].toUShort();
}

QString XQHttpHeadObject::hostPort() const
{
	return host()+":"+ QString::number(port());
}

bool XQHttpHeadObject::contentIsEmpty() const
{
	return m_content.isEmpty();
}

size_t XQHttpHeadObject::contentLength() const
{
	if (!m_header.contains("Content-Length"))
		return 0;
	return m_header["Content-Length"].toULongLong();
}

const QByteArray& XQHttpHeadObject::content() const
{
	return m_content;
}

quint64 XQHttpHeadObject::contentSize() const
{
	return m_content.size();
}

bool XQHttpHeadObject::isContentAcceptFinish()
{
	return contentSize() >= contentLength();
}

QString XQHttpHeadObject::content_toString() const
{
	return content();
}

QJsonDocument XQHttpHeadObject::content_toJson() const
{
	QJsonParseError error;
	QJsonDocument json = QJsonDocument::fromJson(m_content,&error);
	if (error.error != QJsonParseError::NoError) 
	{
		qWarning() << "Parse error: " << error.errorString();
		return QJsonDocument();
	}
	return json;
}

const QByteArray& XQHttpHeadObject::buffer() const
{
	return m_buffer;
}

quint64 XQHttpHeadObject::buffSize() const
{
	return m_buffSize;
}

bool XQHttpHeadObject::isBuffAcceptFinish()
{
	return buffSize()>= contentLength();
}

bool XQHttpHeadObject::isAccepted() const
{
	return m_accept;
}

Http::Head XQHttpHeadObject::type() const
{
	return m_type;
}

void XQHttpHeadObject::accept()
{
	setAccepted(true);
}

void XQHttpHeadObject::ignore()
{
	setAccepted(false);
}

void XQHttpHeadObject::setAccepted(bool accepted)
{
	m_accept = accepted;
}

void XQHttpHeadObject::setData(const QByteArray& header)
{
}

void XQHttpHeadObject::setVersions(Http::Versions type)
{
	m_versions = type;
}

void XQHttpHeadObject::setHeader(const QByteArray& headerName, const QByteArray& headerValue)
{
	m_header[headerName] = headerValue;
}

void XQHttpHeadObject::setHeader(QNetworkRequest::KnownHeaders header, const QByteArray& headerValue)
{
	switch (header)
	{
	case QNetworkRequest::ContentTypeHeader:setHeader("Content-Type",headerValue);
		break;
	case QNetworkRequest::ContentLengthHeader:setHeader("Content-Length", headerValue);
		break;
	case QNetworkRequest::LocationHeader:setHeader("Location", headerValue);
		break;
	case QNetworkRequest::LastModifiedHeader:setHeader("Last-Modified", headerValue);
		break;
	case QNetworkRequest::CookieHeader:setHeader("Cookie", headerValue);
		break;
	case QNetworkRequest::SetCookieHeader:setHeader("Set-Cookie", headerValue);
		break;
	case QNetworkRequest::ContentDispositionHeader:setHeader("Content-Disposition", headerValue);
		break;
	case QNetworkRequest::UserAgentHeader:setHeader("User-Agent", headerValue);
		break;
	case QNetworkRequest::ServerHeader:setHeader("Server", headerValue);
		break;
	case QNetworkRequest::IfModifiedSinceHeader:setHeader("If-Modified-Since", headerValue);
		break;
	case QNetworkRequest::ETagHeader:setHeader("ETag", headerValue);
		break;
	case QNetworkRequest::IfMatchHeader:setHeader("If-Match", headerValue);
		break;
	case QNetworkRequest::IfNoneMatchHeader:setHeader("If-None-Match", headerValue);
		break;
	default:
		break;
	}
}

void XQHttpHeadObject::setHeader(const QByteArrayList& data)
{
	m_header.clear();
	for (auto& byte : data)
	{
		auto row = byte.trimmed();
		auto nSel = row.indexOf(":");
		if (nSel == -1)
			continue;
		auto key = row.left(nSel).trimmed();
		auto value = row.mid(nSel + 1).trimmed();
		m_header[key] = value;
	}
}

void XQHttpHeadObject::setHeader_Date(const QDateTime& date)
{
	setHeader("Date",date.toString("ddd,dd MMM yyyy hh:mm:ss ").toUtf8()+"GMT");
}

void XQHttpHeadObject::clear_header()
{
	m_header.clear();
}

void XQHttpHeadObject::clear()
{
	clear_header();
	setVersions(Http::Versions::HTTP11);
	m_content.clear();
	m_buffSize = 0;
	m_buffer.clear();
}

void XQHttpHeadObject::setContentLength(size_t len)
{
	m_header["Content-Length"] = QByteArray::number(len);
}

void XQHttpHeadObject::setContent(const QByteArray& data)
{
	m_content = data;
	setContentLength(data.size());
}

void XQHttpHeadObject::addContent(const QByteArray& data)
{
	m_content.append(data);
}

void XQHttpHeadObject::setHostPort(QString host, quint16 port)
{
	setHeader("Host",host.toUtf8()+":"+QByteArray::number(port));
}

void XQHttpHeadObject::setBuffer(const QByteArray& data)
{
	m_buffer = data;
	m_buffSize += data.size();
}

void XQHttpHeadObject::clearBuffer()
{
	m_buffer.clear();
	m_buffSize =0;
}

void XQHttpHeadObject::init()
{
	clear();
	setHeader_Date(QDateTime::currentDateTime());
}
